home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / tvdmx.exe / TVDMXBUF.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-07-16  |  21.5 KB  |  846 lines

  1.  
  2. {■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■}
  3. {                            }
  4. {    tvDMXBUF  --Buffered Data Editing Unit        }
  5. {    tvDMX     --data editing project (ver 1.4)    }
  6. {                            }
  7. {    Copyright (c) 1992  Randolph Beck        }
  8. {                P.O. Box  56-0487        }
  9. {                Orlando, FL 32856        }
  10. {                CIS:  72361,753        }
  11. {                            }
  12. {■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■}
  13.  
  14. Unit tvDMXBUF;
  15.  
  16. {$B-,D-,R-,O+,X+,V- }
  17.  
  18. interface
  19.  
  20. uses  
  21.     Objects, Drivers, Views, Dialogs, App, MsgBox,
  22.     RSet, DmxGizma, tvDMX, StdDMX;
  23.  
  24. const
  25.     EmptySlot    =  -1;
  26.  
  27. type
  28.     PSlot    = ^TSlot;
  29.     TSlot    =  RECORD
  30.         Data   : pointer;
  31.         RowNum : integer;
  32.     end;
  33.  
  34.  
  35.     PRowSlots    = ^TRowSlots;
  36.     TRowSlots    =  array [0..99] of TSlot;
  37.  
  38.  
  39.     PDmxEditBuf     = ^TDmxEditBuf;
  40.     PDmxStreamBuf   = ^TDmxStreamBuf;
  41.     PDmxExpBuf      = ^TDmxExpBuf;
  42.     PDmxExpRecInd   = ^TDmxExpRecInd;
  43.     PDmxBufWin      = ^TDmxBufWin;
  44.     PDmxExpBufWin   = ^TDmxExpBufWin;
  45.     PDmxEditRecBuf  = ^TDmxEditRecBuf;
  46.  
  47.  
  48.     TDmxEditBuf   =  OBJECT (TDmxEditor)
  49.         NumSlots    :  integer;
  50.         RowSlot     :  PRowSlots;
  51.         KeyFields   :  set of byte;
  52.         KeyAltered  :  boolean;
  53.         Expandable  :  boolean;
  54.         Appending   :  boolean;
  55.         StepMode    :  boolean;
  56.       constructor Load (var S : TStream);
  57.       procedure Store (var S : TStream);
  58.       procedure LoadStruct (var S : TStream);  VIRTUAL;
  59.       procedure MakeSlots;
  60.       procedure ResetSlots;
  61.       procedure InitStruct (var ATemplate );  VIRTUAL;
  62.       procedure DoneStruct;  VIRTUAL;
  63.       procedure HandleEvent (var Event : TEvent);  VIRTUAL;
  64.       procedure SetState (AState : word; Enable : boolean);  VIRTUAL;
  65.       function  DataAt (RecNum : integer)  : pointer;  VIRTUAL;
  66.       procedure SetUpRecord;  VIRTUAL;
  67.       procedure EvaluateRecord;  VIRTUAL;
  68.       procedure EvaluateField;  VIRTUAL;
  69.       procedure ZeroizeField (Whole : boolean; Field : pDMXfieldrec);  VIRTUAL;
  70.       procedure ResetSize;
  71.       function  RecordLimit : integer;  VIRTUAL;
  72.       function  ErrorFunc : boolean;  VIRTUAL;
  73.       function  SeekRec (RecNum : integer) : boolean;  VIRTUAL;
  74.       function  SeekEnd : boolean;  VIRTUAL;
  75.       function  ReadRec (var RecData ) : boolean;  VIRTUAL;
  76.       function  WriteRec (var RecData ) : boolean;  VIRTUAL;
  77.       private
  78.         NewRecord   :  boolean;  { indicates this is a new record }
  79.     end;
  80.  
  81.  
  82.     TDmxStreamBuf =  OBJECT (TDmxEditBuf)
  83.         Prefix      :  pointer;
  84.         PrefixSize  :  integer;
  85.       procedure LoadStruct (var S : TStream);  VIRTUAL;
  86.       procedure StoreStruct (var S : TStream);  VIRTUAL;
  87.       function  RecordLimit : integer;  VIRTUAL;
  88.       function  ErrorFunc : boolean;  VIRTUAL;
  89.       function  SeekRec (RecNum : integer) : boolean;  VIRTUAL;
  90.       function  SeekEnd : boolean;  VIRTUAL;
  91.       function  ReadRec (var RecData ) : boolean;  VIRTUAL;
  92.       function  WriteRec (var RecData ) : boolean;  VIRTUAL;
  93.     end;
  94.  
  95.  
  96.     TDmxExpBuf    =  OBJECT (TDmxStreamBuf)
  97.       procedure InitData (var AData );  VIRTUAL;
  98.     end;
  99.  
  100.  
  101.     TDmxExpRecInd =  OBJECT (TDmxRecInd)
  102.       procedure Draw;  VIRTUAL;
  103.     end;
  104.  
  105.  
  106.     TDmxBufWin    =  OBJECT (TDmxWindow)
  107.       procedure InitDMX (ATemplate : string;  var AData;
  108.                          ALabels, ARecInd  : PDmxLink;
  109.                          BSize  : longint);  VIRTUAL;
  110.     end;
  111.  
  112.  
  113.     TDmxExpBufWin =  OBJECT (TDmxWindow)
  114.       procedure InitDMX (ATemplate : string;  var AData;
  115.                          ALabels, ARecInd  : PDmxLink;
  116.                          BSize  : longint);  VIRTUAL;
  117.       function  NewRecInd (Len : integer)  : PDmxLink;  VIRTUAL;
  118.     end;
  119.  
  120.  
  121.     TDmxEditRecBuf  =  OBJECT (TDmxEditBuf)
  122.         RecPosition : longint;
  123.       procedure InitData (var AData );  VIRTUAL;
  124.       procedure ZeroizeRecord;  VIRTUAL;
  125.       function  SeekRec (RecNum : integer) : boolean;  VIRTUAL;
  126.       function  SeekEnd : boolean;  VIRTUAL;
  127.       procedure DeleteRec;  VIRTUAL;
  128.       function  WriteRec (var RecData ) : boolean;  VIRTUAL;
  129.       function  AppendRec (var RecData ) : boolean;  VIRTUAL;
  130.       function  UpdateRec (var RecData ) : boolean;  VIRTUAL;
  131.       function  FirstRec : boolean;  VIRTUAL;
  132.       function  LastRec : boolean;  VIRTUAL;
  133.       function  NextRec : boolean;  VIRTUAL;
  134.       function  PrevRec : boolean;  VIRTUAL;
  135.     end;
  136.  
  137.  
  138. const
  139.     RDmxStreamBuf :  TStreamRec = (
  140.         ObjType:   cmDMX + 10;
  141.         VmtLink:   ofs (TypeOf (TDmxStreamBuf)^);
  142.         Load:      @TDmxStreamBuf.Load;
  143.         Store:     @TDmxStreamBuf.Store
  144.       );
  145.  
  146.     RDmxExpBuf    :  TStreamRec = (
  147.         ObjType:   cmDMX + 11;
  148.         VmtLink:   ofs (TypeOf (TDmxExpBuf)^);
  149.         Load:      @TDmxExpBuf.Load;
  150.         Store:     @TDmxExpBuf.Store
  151.       );
  152.  
  153.     RDmxExpRecInd :  TStreamRec = (
  154.         ObjType:   cmDMX + 12;
  155.         VmtLink:   ofs (TypeOf (TDmxExpRecInd)^);
  156.         Load:      @TDmxExpRecInd.Load;
  157.         Store:     @TDmxExpRecInd.Store
  158.       );
  159.  
  160.     RDmxBufWin    :  TStreamRec = (
  161.         ObjType:   cmDMX + 13;
  162.         VmtLink:   ofs (TypeOf (TDmxBufWin)^);
  163.         Load:      @TDmxBufWin.Load;
  164.         Store:     @TDmxBufWin.Store
  165.       );
  166.  
  167.     RDmxExpBufWin :  TStreamRec = (
  168.         ObjType:   cmDMX + 14;
  169.         VmtLink:   ofs (TypeOf (TDmxExpBufWin)^);
  170.         Load:      @TDmxExpBufWin.Load;
  171.         Store:     @TDmxExpBufWin.Store
  172.       );
  173.  
  174.  
  175. implementation
  176.  
  177.  
  178.   { ══ TDmxEditBuf ═══════════════════════════════════════════════════════ }
  179.  
  180.  
  181. constructor TDmxEditBuf.Load (var S : TStream);
  182. begin
  183.   TDmxEditor.Load (S);
  184.   S.Read (KeyFields,  sizeof (KeyFields));
  185.   S.Read (Expandable, sizeof (Expandable));
  186.   S.Read (StepMode,   sizeof (StepMode));
  187. end;
  188.  
  189.  
  190. procedure TDmxEditBuf.Store (var S : TStream);
  191. begin
  192.   TDmxEditor.Store (S);
  193.   S.Write (KeyFields,  sizeof (KeyFields));
  194.   S.Write (Expandable, sizeof (Expandable));
  195.   S.Write (StepMode,   sizeof (StepMode));
  196. end;
  197.  
  198.  
  199. procedure TDmxEditBuf.LoadStruct (var S : TStream);
  200. begin
  201.   TDmxEditor.LoadStruct (S);
  202.   MakeSlots;
  203. end;
  204.  
  205.  
  206. procedure TDmxEditBuf.MakeSlots;
  207. var i  : integer;
  208. begin
  209.   If InitValid and (RecordSize > 0) then
  210.     begin
  211.     NumSlots := ScreenHeight;
  212.     If (HiResScreen and (NumSlots < 30)) then NumSlots := 46;
  213.     If (NumSlots < Size.Y) then NumSlots := Size.Y;
  214.     GetMem (RowSlot, NumSlots * sizeof (TSlot));
  215.     fillchar (RowSlot^, NumSlots * sizeof (TSlot), 0);
  216.     For i := 0 to pred (NumSlots) do
  217.       begin
  218.       If ((MaxAvail shr 4) > RecordSize) then
  219.         begin
  220.         RowSlot^ [i].RowNum := EmptySlot;
  221.         GetMem (RowSlot^ [i].Data, RecordSize);
  222.         end
  223.        else
  224.         InitValid := FALSE;
  225.       end;
  226.     end;
  227. end;
  228.  
  229.  
  230. procedure TDmxEditBuf.ResetSlots;
  231. var i : integer;
  232. begin
  233.   If (NumSlots > 0) then
  234.     For i := 0 to pred (NumSlots) do RowSlot^ [i].RowNum := EmptySlot;
  235. end;
  236.  
  237.  
  238. procedure TDmxEditBuf.InitStruct (var ATemplate );
  239. begin
  240.   TDmxEditor.InitStruct (ATemplate);
  241.   MakeSlots;
  242. end;
  243.  
  244.  
  245. procedure TDmxEditBuf.DoneStruct;
  246. var i : integer;
  247. begin
  248.   If (RowSlot <> nil) then
  249.     begin
  250.     For i := 0 to pred (NumSlots) do
  251.       If (RowSlot^ [i].Data <> nil) then FreeMem (RowSlot^ [i].Data, RecordSize);
  252.     FreeMem (RowSlot, NumSlots * sizeof (TSlot));
  253.     RowSlot  := nil;
  254.     NumSlots := 0;
  255.     end;
  256.   TDmxEditor.DoneStruct;
  257. end;
  258.  
  259.  
  260. procedure TDmxEditBuf.HandleEvent (var Event : TEvent);
  261. begin
  262.   With Event do
  263.     If (What = evBroadcast) and (NumSlots > 0) and
  264.         (((Command = cmDMX_DrawData) and (WorkingData = InfoPtr))
  265.        or
  266.          ((Command = cmDMX_Draw)
  267.         and (InfoPtr <> @Self)
  268.         and (PDmxScroller (InfoPtr)^.WorkingData = WorkingData)))
  269.      then
  270.       begin
  271.       ResetSlots;
  272.       end;
  273.   TDmxEditor.HandleEvent (Event);
  274. end;
  275.  
  276.  
  277. procedure TDmxEditBuf.SetState (AState : word; Enable : boolean);
  278. begin
  279.   If Enable and (AState and sfFocused <> 0) and (not RecordSelected) and
  280.      Expandable and (CurrentField <> nil) then
  281.     ResetSize;
  282.   TDmxEditor.SetState (AState, Enable);
  283. end;
  284.  
  285.  
  286. function  TDmxEditBuf.DataAt (RecNum : integer) : pointer;
  287. var  Slot : integer;
  288.     function  SeekOK : boolean;
  289.     var L : longint;
  290.     begin
  291.       L := RecNum;
  292.       If Expandable and (L >= RecordLimit) then
  293.         begin
  294.         NewRecord := TRUE;
  295.         SeekOK    := TRUE;
  296.         end
  297.        else
  298.         SeekOK := SeekRec (RecNum);
  299.     end;
  300. begin
  301.   If (not InitValid) or (NumSlots = 0) or (RecordSize = 0) then
  302.     begin
  303.     Locked := TRUE;
  304.     DataAt := nil;
  305.     Exit;
  306.     end;
  307.   Slot  := RecNum mod NumSlots;
  308.   NewRecord := FALSE;
  309.   If (RowSlot^ [Slot].RowNum <> RecNum) then
  310.     begin
  311.     FillChar (RowSlot^ [Slot].Data^, RecordSize, 0);
  312.     RowSlot^ [Slot].RowNum := RecNum;
  313.     Repeat
  314.     Until (SeekOK and (NewRecord or ReadRec (RowSlot^ [Slot].Data^)))
  315.         or ErrorFunc;
  316.     end;
  317.   DataAt := RowSlot^ [Slot].Data;
  318. end;
  319.  
  320.  
  321. procedure TDmxEditBuf.SetUpRecord;
  322. begin
  323.   If (NumSlots > 0) then
  324.     RowSlot^ [CurrentRecord mod NumSlots].RowNum := EmptySlot;
  325.   TDmxEditor.SetUpRecord;
  326.   RedrawRecord := TRUE;
  327.   Appending    := NewRecord;
  328. end;
  329.  
  330.  
  331. procedure TDmxEditBuf.EvaluateRecord;
  332.     function  DoWrite : boolean;
  333.     begin
  334.       DoWrite := WriteRec (RowSlot^ [CurrentRecord mod NumSlots].Data^);
  335.     end;
  336. begin
  337.   If RecordAltered then
  338.     begin
  339.     RecordAltered := FALSE;
  340.     If Appending then
  341.       begin
  342.       Repeat until (SeekEnd and DoWrite) or ErrorFunc;
  343.       ResetSize;
  344.       Appending := FALSE;
  345.       end
  346.     else
  347.     If StepMode then
  348.       begin
  349.       Repeat until DoWrite or ErrorFunc;
  350.       end
  351.     else
  352.       begin
  353.       Repeat until (SeekRec (CurrentRecord) and DoWrite) or ErrorFunc;
  354.       end;
  355.     end;
  356.   TDmxEditor.EvaluateRecord;
  357.   If KeyAltered then
  358.     begin
  359.     KeyAltered := FALSE;
  360.     ResetSlots;
  361.     DrawView;
  362.     end;
  363. end;
  364.  
  365.  
  366. procedure TDmxEditBuf.EvaluateField;
  367. begin
  368.   If FieldAltered and (CurrentField^.fieldnum in KeyFields) then KeyAltered := TRUE;
  369.   TDmxEditor.EvaluateField;
  370. end;
  371.  
  372.  
  373. procedure TDmxEditBuf.ZeroizeField (Whole : boolean; Field : pDMXfieldrec);
  374. begin
  375.   TDmxEditor.ZeroizeField (Whole, Field);
  376.   If (Field <> nil) and (Field^.fieldnum in KeyFields) then KeyAltered := TRUE;
  377. end;
  378.  
  379.  
  380. procedure TDmxEditBuf.ResetSize;
  381. var  Recs : longint;
  382.      A    : string;
  383. begin
  384.   Recs := RecordLimit;
  385.   If Expandable and (Recs < 32766) then Inc (Recs);
  386.   If (Recs < 0) then Recs := 0;
  387.   If (Recs * RecordSize <> DataBlockSize) then
  388.     begin
  389.     DataBlockSize := Recs * RecordSize;
  390.     SetLimit (Limit.X, Recs);
  391.     If (succ (CurrentRecord) > Recs) then CurrentRecord := Recs - 1;
  392.     ResetSlots;
  393.     end;
  394. end;
  395.  
  396.  
  397. function  TDmxEditBuf.RecordLimit : integer;
  398. { pseudo-abstract method to return the maximum number of records possible }
  399. var  L : longint;
  400. begin
  401.   If (RecordSize > 0) then
  402.     begin
  403.     L := (DataBlockSize div RecordSize);
  404.     If Expandable and (L > 0) then Dec (L);
  405.     RecordLimit := integer (L);
  406.     end
  407.    else
  408.     RecordLimit := 0;
  409. end;
  410.  
  411.  
  412. function  TDmxEditBuf.ErrorFunc : boolean;
  413. { pseudo-abstract method to handle access errors }
  414. begin
  415.  { This method should take care of the error
  416.    and return TRUE if the error can be ignored
  417.    or FALSE if the operation should be repeated. }
  418.  
  419.   ErrorFunc := (SystemError (14, 0) = 1);
  420. end;
  421.  
  422.  
  423. function  TDmxEditBuf.SeekRec (RecNum : integer) : boolean;
  424. { abstract virtual method to seek to the record position }
  425. begin
  426.   Abstract;
  427.  { This method should seek to the given record
  428.    number, and return TRUE if there is no error.
  429.   }
  430. end;
  431.  
  432.  
  433. function  TDmxEditBuf.SeekEnd : boolean;
  434. { pseudo-abstract method used for expandable databases }
  435. begin
  436.  { This method should seek to the end of the database, and
  437.    return TRUE if there is no error.  Many database tools
  438.    will just require that you clear its record buffer.
  439.    The default here is to seek to the limit using method SeekRec().
  440.   }
  441.   SeekRec (RecordLimit);
  442.   SeekEnd := TRUE;
  443. end;
  444.  
  445.  
  446. function  TDmxEditBuf.ReadRec (var RecData ) : boolean;
  447. { abstract virtual method to read a record }
  448. begin
  449.   Abstract;
  450.  { This method should read a record and return TRUE if there is no error. }
  451. end;
  452.  
  453.  
  454. function  TDmxEditBuf.WriteRec (var RecData ) : boolean;
  455. { abstract virtual method to write a record }
  456. begin
  457.   Abstract;
  458.  { This method should write a record and return TRUE if there is no error. }
  459. end;
  460.  
  461.  
  462.   { ══ TDmxStreamBuf ═════════════════════════════════════════════════════ }
  463.  
  464.  
  465. procedure TDmxStreamBuf.LoadStruct (var S : TStream);
  466. begin
  467.   TDmxEditBuf.LoadStruct (S);
  468.   S.Read (PrefixSize, sizeof (PrefixSize));
  469.   Prefix := nil;
  470. end;
  471.  
  472.  
  473. procedure TDmxStreamBuf.StoreStruct (var S : TStream);
  474. begin
  475.   TDmxEditBuf.StoreStruct (S);
  476.   S.Write (PrefixSize, sizeof (PrefixSize));
  477. end;
  478.  
  479.  
  480. function  TDmxStreamBuf.RecordLimit : integer;
  481. var L : longint;
  482. begin
  483.   If (RecordSize = 0) then
  484.     RecordLimit := 0
  485.    else
  486.     begin
  487.     L := (PStream (WorkingData)^.GetSize - PrefixSize) div RecordSize;
  488.     If (L > 32766) then L := 32766;
  489.     RecordLimit := integer (L);
  490.     end;
  491. end;
  492.  
  493.  
  494. function  TDmxStreamBuf.ErrorFunc : boolean;
  495. { virtual method to handle stream errors }
  496. begin
  497.   ErrorFunc := TDmxEditBuf.ErrorFunc;
  498.   PStream (WorkingData)^.Reset;
  499. end;
  500.  
  501.  
  502. function  TDmxStreamBuf.SeekRec (RecNum : integer) : boolean;
  503. var  L : longint;
  504. begin
  505.   PStream (WorkingData)^.Reset;
  506.   L := RecNum;
  507.   PStream (WorkingData)^.Seek (PrefixSize + (L * RecordSize));
  508.   SeekRec := (PStream (WorkingData)^.Status = stOk);
  509. end;
  510.  
  511.  
  512. function  TDmxStreamBuf.SeekEnd : boolean;
  513. var  L : longint;
  514. begin
  515.   L := RecordLimit;
  516.   PStream (WorkingData)^.Seek (PrefixSize + (L * RecordSize));
  517.   SeekEnd := (PStream (WorkingData)^.Status = stOk);
  518. end;
  519.  
  520.  
  521. function  TDmxStreamBuf.ReadRec (var RecData ) : boolean;
  522. begin
  523.   With PStream (WorkingData)^ do
  524.     begin
  525.     If (Status <> stOk) then Reset;
  526.     Read (RecData, RecordSize);
  527.     ReadRec := (Status = stOk);
  528.     end;
  529. end;
  530.  
  531.  
  532. function  TDmxStreamBuf.WriteRec (var RecData ) : boolean;
  533. begin
  534.   With PStream (WorkingData)^ do
  535.     begin
  536.     If (Status <> stOk) then Reset;
  537.     Write (RecData, RecordSize);
  538.     WriteRec := (Status = stOk);
  539.     end;
  540. end;
  541.  
  542.  
  543.   { ══ TDmxExpRecInd ═════════════════════════════════════════════════════ }
  544.  
  545.  
  546. procedure TDmxExpRecInd.Draw;
  547. var  A,E  : string [80];
  548.      B    : TDrawBuffer;
  549.      C    : word;
  550. begin
  551.   C := GetColor (6);
  552.   MoveChar (B, '═', C, Size.X);
  553.   Str (succ (Link^.CurrentRecord):1, A);
  554.   Str (pred (Link^.Limit.Y):1,       E);
  555.   If Link^.CurrentRecord = pred (Link^.Limit.Y) then A := 'Add';
  556.   A := A + '/' + E;
  557.   If length (A) > Size.X then A [0] := chr (length (A) - succ (length (E)));
  558.   If length (A) > Size.X then
  559.     begin
  560.     MoveChar (B, showOVERFLOW, C, Size.X);
  561.     end
  562.    else
  563.     begin
  564.     If length (A) < Size.X then A := A + ' ';
  565.     If length (A) < Size.X then A := ' ' + A;
  566.     MoveStr (B [succ ((Size.X) - length (A)) shr 1], A, C);
  567.     end;
  568.   WriteBuf (0, 0, Size.X, 1, B);
  569. end;
  570.  
  571.  
  572.   { ══ TDmxExpBuf ════════════════════════════════════════════════════════ }
  573.  
  574.  
  575. procedure TDmxExpBuf.InitData (var AData );
  576. begin
  577.   TDmxStreamBuf.InitData (AData);
  578.   PrefixSize    := DataBlockSize;
  579.   Expandable    := TRUE;
  580.   ResetSize;
  581. end;
  582.  
  583.  
  584.   { ══ TDmxBufWin ════════════════════════════════════════════════════════ }
  585.  
  586.  
  587. procedure TDmxBufWin.InitDMX (ATemplate : string;  var AData;
  588.                               ALabels, ARecInd : PDmxLink;  BSize : longint);
  589. var  R     : TRect;
  590. begin
  591.   GetExtent (R);
  592.   R.Grow (-1,-1);
  593.   Inc (R.A.Y, 2);
  594.  
  595.   Insert (New (PDmxStreamBuf, Init (ATemplate, AData, BSize, R,
  596.                                ALabels, ARecInd,
  597.                                StandardScrollBar (sbHorizontal+ sbHandleKeyboard),
  598.                                StandardScrollBar (sbVertical  + sbHandleKeyboard))));
  599.  
  600. end;
  601.  
  602.  
  603.   { ══ TDmxExpBufWin ═════════════════════════════════════════════════════ }
  604.  
  605.  
  606. procedure TDmxExpBufWin.InitDMX (ATemplate : string;  var AData;
  607.                                  ALabels, ARecInd : PDmxLink;  BSize : longint);
  608. var  R     : TRect;
  609. begin
  610.   GetExtent (R);
  611.   R.Grow (-1,-1);
  612.   Inc (R.A.Y, 2);
  613.  
  614.   Insert (New (PDmxExpBuf, Init (ATemplate, AData, BSize, R,
  615.                                  ALabels, ARecInd,
  616.                                  StandardScrollBar (sbHorizontal+ sbHandleKeyboard),
  617.                                  StandardScrollBar (sbVertical  + sbHandleKeyboard))));
  618.  
  619. end;
  620.  
  621.  
  622. function  TDmxExpBufWin.NewRecInd (Len : integer)  : PDmxLink;
  623. var  ARecInd   : PDmxExpRecInd;
  624.      R         : TRect;
  625. begin
  626.   If Len <= 0 then
  627.     NewRecInd := nil
  628.    else
  629.     begin
  630.     GetExtent (R);
  631.     Inc (R.A.X);
  632.     R.A.Y  := pred (R.B.Y);
  633.     R.Grow (-1, 0);
  634.     If R.B.X - R.A.X > Len then R.B.X := R.A.X + Len;
  635.     R.B.Y := succ (R.A.Y);
  636.     ARecInd := New (PDmxExpRecInd, Init (R, Len));
  637.     Insert (ARecInd);
  638.     NewRecInd := ARecInd;
  639.     end;
  640. end;
  641.  
  642.  
  643.   { ══ TDmxEditRecBuf ════════════════════════════════════════════════════ }
  644.  
  645.  
  646. procedure TDmxEditRecBuf.InitData (var AData );
  647. begin
  648.   TDmxEditBuf.InitData (AData);
  649.   StepMode := TRUE;
  650. end;
  651.  
  652.  
  653. procedure TDmxEditRecBuf.ZeroizeRecord;
  654. begin
  655.   If Appending then
  656.     begin
  657.     TDmxEditBuf.ZeroizeRecord;
  658.     RecordAltered := FALSE;
  659.     FieldAltered  := FALSE;
  660.     end
  661.    else
  662.     begin
  663.     Vidis := TRUE;
  664.    { Prevents tvDMX from resetting the current field and record when this
  665.      view loses the focus.  This should only be used for MessageBoxes.
  666.     }
  667.     If (MessageBox ('Do you wish to DELETE this record?', nil,
  668.                     mfConfirmation + mfYesNoCancel) = cmYes)
  669.      then
  670.       begin
  671.       DeleteRec;
  672.       Appending  := TRUE;
  673.       ResetSize;
  674.       DrawView;
  675.       If RecordSelected then
  676.         begin
  677.         RecordAltered := FALSE;
  678.         FieldAltered  := FALSE;
  679.         EvaluateField;
  680.         KeyAltered := TRUE;
  681.         EvaluateRecord;
  682.         SetupRecord;
  683.         SetupField;
  684.         end
  685.        else
  686.         begin
  687.         ResetSize;
  688.         DrawView;
  689.         end;
  690.       end;
  691.     Vidis := FALSE;  { always set this back to FALSE }
  692.     end;
  693. end;
  694.  
  695.  
  696. function  TDmxEditRecBuf.SeekRec (RecNum : integer) : boolean;
  697. { uses FirstRec(), LastRec(), NextRec() and PrevRec() to seek to a record }
  698. var  B      : boolean;
  699.      EndNum : integer;
  700.     function  LastRecord : boolean;
  701.     begin
  702.       If (RecordSize = 0) then
  703.         begin
  704.         EndNum := 0;
  705.         LastRecord := FALSE;
  706.         end
  707.        else
  708.         begin
  709.         EndNum := (DataBlockSize div RecordSize) - 1;
  710.         If Expandable then Dec (EndNum);
  711.         LastRecord := (RecNum = EndNum);
  712.         end;
  713.     end;
  714. begin
  715.   B := TRUE;
  716.   If (RecNum = 0) then
  717.     begin
  718.     B := FirstRec;
  719.     RecPosition := 0;
  720.     end
  721.    else
  722.     If LastRecord then
  723.       begin
  724.       B := LastRec;
  725.       RecPosition := EndNum;
  726.       end
  727.      else
  728.       begin
  729.       While (RecPosition < RecNum) and B do
  730.         begin
  731.         B := NextRec;
  732.         If B then Inc (RecPosition);
  733.         end;
  734.       While (RecPosition > RecNum) and B do
  735.         begin
  736.         B := PrevRec;
  737.         If B then Dec (RecPosition);
  738.         end;
  739.       end;
  740.   SeekRec := B;
  741. end;
  742.  
  743.  
  744. function  TDmxEditRecBuf.SeekEnd : boolean;
  745. begin
  746.   SeekEnd := TRUE;
  747. end;
  748.  
  749.  
  750. procedure TDmxEditRecBuf.DeleteRec;
  751. { abstract method to delete the record }
  752. begin
  753.  { This method should be overridden to delete the current record. }
  754. end;
  755.  
  756.  
  757. function  TDmxEditRecBuf.WriteRec (var RecData ) : boolean;
  758. { virtual method to write a record }
  759. begin
  760.   If Appending then
  761.     begin
  762.     KeyAltered := (KeyFields <> []);
  763.     WriteRec := AppendRec (RecData);
  764.     end
  765.    else
  766.     WriteRec := UpdateRec (RecData);
  767. end;
  768.  
  769.  
  770. function  TDmxEditRecBuf.AppendRec (var RecData ) : boolean;
  771. { abstract virtual method to write a record }
  772. begin
  773.   Abstract;
  774.  { This method should append a record and return TRUE if there is no error. }
  775. end;
  776.  
  777.  
  778. function  TDmxEditRecBuf.UpdateRec (var RecData ) : boolean;
  779. { abstract virtual method to update the current record }
  780. begin
  781.   Abstract;
  782.  { This method should write a record and return TRUE if there is no error. }
  783. end;
  784.  
  785.  
  786. function  TDmxEditRecBuf.FirstRec : boolean;
  787. { pseudo-abstract method to seek to the first record position }
  788. begin
  789.  { This method should be overridden to seek directly to the
  790.    first record, and it should return TRUE if there is no error.
  791.    The default method just repeats PrevRec() until it receives
  792.    an error.
  793.   }
  794.   Repeat until not PrevRec;
  795.   FirstRec := TRUE;
  796. end;
  797.  
  798.  
  799. function  TDmxEditRecBuf.LastRec : boolean;
  800. { abstract virtual method to seek to the last record position }
  801. begin
  802.   Abstract;
  803.  { This method should be overridden to seek to the last record
  804.    position, and it should return TRUE if there is no error.
  805.   }
  806. end;
  807.  
  808.  
  809. function  TDmxEditRecBuf.NextRec : boolean;
  810. { abstract virtual method to seek to the next record position }
  811. begin
  812.   Abstract;
  813.  { This method should be overridden to seek to the next record
  814.    position, and it should return TRUE if there is no error.
  815.   }
  816. end;
  817.  
  818.  
  819. function  TDmxEditRecBuf.PrevRec : boolean;
  820. { abstract virtual method to seek to the previous record position }
  821. begin
  822.  { This method should be overridden to seek to the previous record
  823.    position, and it should return TRUE if there is no error.
  824.   }
  825. end;
  826.  
  827.  
  828.   { ══════════════════════════════════════════════════════════════════════ }
  829.  
  830.  
  831. procedure RegisterDMXBUF;
  832. begin
  833.   RegisterType (RDmxStreamBuf);
  834.   RegisterType (RDmxExpBuf);
  835.   RegisterType (RDmxExpRecInd);
  836.   RegisterType (RDmxBufWin);
  837.   RegisterType (RDmxExpBufWin);
  838. end;
  839.  
  840.  
  841.   { ══════════════════════════════════════════════════════════════════════ }
  842.  
  843.  
  844.  
  845. End.
  846.